package com.tsyz.shared.util;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * CompletableFuture练习类
 * 企业级CompletableFuture使用示例，演示各种异步编程场景
 */
public class CompletableFuturePractice {
    
    // 线程池实例
    private final ExecutorService threadPool;
    
    public CompletableFuturePractice(ExecutorService threadPool) {
        this.threadPool = threadPool;
    }
    
    /**
     * 基础异步任务示例
     * @return CompletableFuture<String> 异步结果
     */
    public CompletableFuture<String> basicAsyncExample() {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟业务处理
            sleep(1000);
            return "基础异步任务完成";
        }, threadPool);
    }
    
    /**
     * 多任务并行处理示例
     * @param taskCount 任务数量
     * @return CompletableFuture<List<String>> 并行处理结果
     */
    public CompletableFuture<List<String>> parallelTasksExample(int taskCount) {
        // 创建多个并行任务
        List<CompletableFuture<String>> futures = IntStream.range(1, taskCount + 1)
                .mapToObj(i -> CompletableFuture.supplyAsync(() -> {
                    // 模拟不同的处理时间
                    sleep(100 * i);
                    return "任务-" + i + "-完成";
                }, threadPool))
                .collect(Collectors.toList());
        
        // 等待所有任务完成并合并结果
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .thenApply(v -> futures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList()));
    }
    
    /**
     * 任务链式调用示例
     * @param input 输入参数
     * @return CompletableFuture<String> 链式处理结果
     */
    public CompletableFuture<String> chainedTasksExample(String input) {
        return CompletableFuture
                // 第一步：数据预处理
                .supplyAsync(() -> {
                    System.out.println("线程 " + Thread.currentThread().getName() + " 执行数据预处理");
                    sleep(500);
                    return input.toUpperCase();
                }, threadPool)
                // 第二步：业务处理
                .thenCompose(processedData -> CompletableFuture.supplyAsync(() -> {
                    System.out.println("线程 " + Thread.currentThread().getName() + " 执行业务处理");
                    sleep(800);
                    return "处理后数据: " + processedData;
                }, threadPool))
                // 第三步：结果格式化
                .thenApply(result -> {
                    System.out.println("线程 " + Thread.currentThread().getName() + " 执行结果格式化");
                    return "[" + System.currentTimeMillis() + "] " + result;
                });
    }
    
    /**
     * 异常处理示例
     * @param shouldThrow 是否抛出异常
     * @return CompletableFuture<String> 处理结果
     */
    public CompletableFuture<String> exceptionHandlingExample(boolean shouldThrow) {
        return CompletableFuture
                .supplyAsync(() -> {
                    System.out.println("在线程 " + Thread.currentThread().getName() + " 中执行任务");
                    if (shouldThrow) {
                        throw new RuntimeException("模拟业务异常");
                    }
                    sleep(500);
                    return "正常执行结果";
                }, threadPool)
                .exceptionally(throwable -> {
                    System.err.println("捕获异常: " + throwable.getMessage());
                    return "异常处理结果: 使用默认值";
                })
                .thenApply(result -> "最终结果: " + result);
    }
    
    /**
     * 组合任务示例
     * @return CompletableFuture<String> 组合结果
     */
    public CompletableFuture<String> combinedTasksExample() {
        // 创建两个独立的异步任务
        CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {
            sleep(1000);
            return "任务A结果";
        }, threadPool);
        
        CompletableFuture<Integer> task2 = CompletableFuture.supplyAsync(() -> {
            sleep(1500);
            return 42;
        }, threadPool);
        
        // 组合两个任务的结果
        return task1.thenCombine(task2, (result1, result2) -> 
            "组合结果: " + result1 + " + " + result2 + " = " + (result1 + result2));
    }
    
    /**
     * 工具方法：模拟耗时操作
     * @param millis 毫秒数
     */
    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 获取线程池引用
     * @return ExecutorService 线程池实例
     */
    public ExecutorService getThreadPool() {
        return threadPool;
    }
}
